/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//    Copyright(c) 2000 - 2001 Intel Corporation. All Rights Reserved.
//
//  VSS: 
//     $Workfile: $
//     $Revision: $
//     $Date:     $
//     $Archive:  $
//
//  Description:
//      Intel(R) Integrated Performance Primitives - JPEG Helper file.
//      This file contains Forward DCT functions. 
//
//  History:
//     Date         Author        Changes
//     2000/5/18   Jerry Hu       Created  (Version 0.1, Lee algorithm )
//     2000/12/22  Jerry Hu       Modified (Version 0.2, Winograd algorithm)
//
********************************************************************************/
#include "_ippjpeg.h"

/*
// cos ((2*pi)/16) = 0.9238795325112867561
// cos ((6*pi)/16) = 0.3826834323650897717
// cos ((2*pi)/16) + cos ((6*pi)/16) = 
//                   1.3065629648763765278
// cos ((2*pi)/16) - cos ((6*pi)/16) = 
//                   0.5411961001461969844
*/

#define _SQRT2_2   2896  /* sqrt(2)/2 (15:23170)*/
#define _C_2A6_16  5352  /* cos ((2*pi)/16) + cos ((6*pi)/16) (15:42813)*/
#define _C_2S6_16  2217  /* cos ((2*pi)/16) - cos ((6*pi)/16) (15:17734)*/
#define _C_6_16    1567  /* cos ((6*pi)/16) (15:12540)*/

#define _CONSTFACTOR    12
#define _H_MP           2048
#define _V_MP           2048

/******************************************************************************
// Name:             ippiDCTQuantFwd_JPEG_16s_I
// Description:      Performs Forward DCT and quantization for single block.
// Input Arguments: 
//          pSrcDst: Identifies source data in 8x8.
//      pQuantTable: Identifies quantization table which was generated by
//                   ippiDCTQuantFwdTableInit_JPEG_16u32s.
//
// Output Arguments:
//          pSrcDst: Identifies destination data in 8x8.
//                  
// Remarks:      
//                   1. The start address of "pSrcDst" and  " pQuantTable"
//                      shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiDCTQuantFwd_JPEG_16s_I) (Ipp16s* pSrcDst, 
                                               const Ipp16u *pQuantTable)
{
    int i;
    int c0,c1,c2,c3,c4,c5,c6,c7;
    int d0,d1,d2,d3,d4,d5,d6,d7;
    int e0, e1, e2, e3, a,b,c,d;
    int value, value1, value2;
    Ipp16s *pSrcDstCur;

    _IPP_CHECK_ARG(NULL!=pSrcDst);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pSrcDst));
    _IPP_CHECK_ARG(NULL!=pQuantTable);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pQuantTable));

    pSrcDstCur=pSrcDst;

    /* Do 1D-DCT in the each row */
    for (i=8; i>0; i--) {

        c0=pSrcDstCur[0]+pSrcDstCur[7];
        c1=pSrcDstCur[1]+pSrcDstCur[6];
        c2=pSrcDstCur[2]+pSrcDstCur[5];
        c3=pSrcDstCur[3]+pSrcDstCur[4];
        c4=pSrcDstCur[3]-pSrcDstCur[4];
        c5=pSrcDstCur[2]-pSrcDstCur[5];
        c6=pSrcDstCur[1]-pSrcDstCur[6];
        c7=pSrcDstCur[0]-pSrcDstCur[7];

        e0=c0+c3;
        e1=c1+c2;
        e2=c1-c2;
        e3=c0-c3;

        pSrcDstCur[0]=(Ipp16s)(e0+e1);
        pSrcDstCur[4]=(Ipp16s)(e0-e1);
    
        value=((e2+e3)*_SQRT2_2+_H_MP)>>_CONSTFACTOR;
        pSrcDstCur[2]=(Ipp16s)(e3+value);
        pSrcDstCur[6]=(Ipp16s)(e3-value);

        a=c4+c5;
        b=c5+c6;
        c=c6+c7;
        d=c7;

        value1=b*_SQRT2_2;

        value2=(a-c)*_C_6_16;
        value=c*_C_2A6_16+value2;
    
        pSrcDstCur[1]=(Ipp16s)(d+((value1+value+_H_MP)>>_CONSTFACTOR));
        pSrcDstCur[7]=(Ipp16s)(d+((value1-value+_H_MP)>>_CONSTFACTOR));

        value=a*_C_2S6_16+value2;    

        pSrcDstCur[5]=(Ipp16s)(d-((value1-value+_H_MP)>>_CONSTFACTOR));
        pSrcDstCur[3]=(Ipp16s)(d-((value1+value+_H_MP)>>_CONSTFACTOR));

        pSrcDstCur+=8;
    }

    pSrcDstCur=pSrcDst;

    /* Do 1D-DCT in the each col */
    for (i=8; i>0; i--) {

        c0=pSrcDstCur[0*8]+pSrcDstCur[7*8];
        c1=pSrcDstCur[1*8]+pSrcDstCur[6*8];
        c2=pSrcDstCur[2*8]+pSrcDstCur[5*8];
        c3=pSrcDstCur[3*8]+pSrcDstCur[4*8];
        c4=pSrcDstCur[3*8]-pSrcDstCur[4*8];
        c5=pSrcDstCur[2*8]-pSrcDstCur[5*8];
        c6=pSrcDstCur[1*8]-pSrcDstCur[6*8];
        c7=pSrcDstCur[0*8]-pSrcDstCur[7*8];

        e0=c0+c3;
        e1=c1+c2;
        e2=c1-c2;
        e3=c0-c3;

        d0=e0+e1;
        d4=e0-e1;
    
        value=((e2+e3)*_SQRT2_2+_V_MP)>>_CONSTFACTOR;
        d2=e3+value;
        d6=e3-value;

        a=c4+c5;
        b=c5+c6;
        c=c6+c7;
        d=c7;

        value1=b*_SQRT2_2;

        value2=(a-c)*_C_6_16;
        value=c*_C_2A6_16+value2;
    
        d1=d+((value1+value+_V_MP)>>_CONSTFACTOR);
        d7=d+((value1-value+_V_MP)>>_CONSTFACTOR);

        value=a*_C_2S6_16+value2;    

        d5=d-((value1-value+_V_MP)>>_CONSTFACTOR);
        d3=d-((value1+value+_V_MP)>>_CONSTFACTOR);

        pSrcDstCur[0*8]=(Ipp16s)((d0*pQuantTable[0]+16384)>>15);
        pSrcDstCur[1*8]=(Ipp16s)((d1*pQuantTable[1]+16384)>>15);
        pSrcDstCur[2*8]=(Ipp16s)((d2*pQuantTable[2]+16384)>>15);
        pSrcDstCur[3*8]=(Ipp16s)((d3*pQuantTable[3]+16384)>>15);
        pSrcDstCur[4*8]=(Ipp16s)((d4*pQuantTable[4]+16384)>>15);
        pSrcDstCur[5*8]=(Ipp16s)((d5*pQuantTable[5]+16384)>>15);
        pSrcDstCur[6*8]=(Ipp16s)((d6*pQuantTable[6]+16384)>>15);
        pSrcDstCur[7*8]=(Ipp16s)((d7*pQuantTable[7]+16384)>>15);

        pSrcDstCur++;
        pQuantTable+=8;
    }
    return IPP_STATUS_OK;
}

/******************************************************************************
// Name:             ippiDCTQuantFwd_JPEG_16s
// Description:      Performs Forward DCT and quantization for single block.
// Input Arguments: 
//             pSrc: Identifies source data in 8x8.
//      pQuantTable: Identifies quantization table which was generated by
//                   ippiDCTQuantFwdTableInit_JPEG_16u32s.
//
// Output Arguments:
//             pDst: Identifies destination data in 8x8.
//                  
// Remarks:      
//                   1. The start address of "pSrc", "pDst" and "pQuantTable"
//                      shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiDCTQuantFwd_JPEG_16s) (const Ipp16s* pSrc, 
                                             Ipp16s *pDst, 
                                             const Ipp16u *pQuantTable)
{
    int i;
    int c0,c1,c2,c3,c4,c5,c6,c7;
    int d0,d1,d2,d3,d4,d5,d6,d7;
    int e0, e1, e2, e3, a,b,c,d;
    int value, value1, value2;
    Ipp16s *pTempPtr;

    _IPP_CHECK_ARG((NULL!=pSrc)&&(NULL!=pDst));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pSrc));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDst));
    _IPP_CHECK_ARG(NULL!=pQuantTable);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pQuantTable));

    pTempPtr=pDst;

    /* Do 1D-DCT in the each row */
    for (i=8; i>0; i--) {

        c0=pSrc[0]+pSrc[7];
        c1=pSrc[1]+pSrc[6];
        c2=pSrc[2]+pSrc[5];
        c3=pSrc[3]+pSrc[4];
        c4=pSrc[3]-pSrc[4];
        c5=pSrc[2]-pSrc[5];
        c6=pSrc[1]-pSrc[6];
        c7=pSrc[0]-pSrc[7];

        e0=c0+c3;
        e1=c1+c2;
        e2=c1-c2;
        e3=c0-c3;

        pTempPtr[0]=(Ipp16s)(e0+e1);
        pTempPtr[4]=(Ipp16s)(e0-e1);
    
        value=((e2+e3)*_SQRT2_2+_H_MP)>>_CONSTFACTOR;
        pTempPtr[2]=(Ipp16s)(e3+value);
        pTempPtr[6]=(Ipp16s)(e3-value);

        a=c4+c5;
        b=c5+c6;
        c=c6+c7;
        d=c7;

        value1=b*_SQRT2_2;

        value2=(a-c)*_C_6_16;
        value=c*_C_2A6_16+value2;
    
        pTempPtr[1]=(Ipp16s)(d+((value1+value+_H_MP)>>_CONSTFACTOR));
        pTempPtr[7]=(Ipp16s)(d+((value1-value+_H_MP)>>_CONSTFACTOR));

        value=a*_C_2S6_16+value2;    

        pTempPtr[5]=(Ipp16s)(d-((value1-value+_H_MP)>>_CONSTFACTOR));
        pTempPtr[3]=(Ipp16s)(d-((value1+value+_H_MP)>>_CONSTFACTOR));

        pSrc+=8;
        pTempPtr+=8;
    }

    pTempPtr=pDst;

    /* Do 1D-DCT in the each col */
    for (i=8; i>0; i--) {

        c0=pTempPtr[0*8]+pTempPtr[7*8];
        c1=pTempPtr[1*8]+pTempPtr[6*8];
        c2=pTempPtr[2*8]+pTempPtr[5*8];
        c3=pTempPtr[3*8]+pTempPtr[4*8];
        c4=pTempPtr[3*8]-pTempPtr[4*8];
        c5=pTempPtr[2*8]-pTempPtr[5*8];
        c6=pTempPtr[1*8]-pTempPtr[6*8];
        c7=pTempPtr[0*8]-pTempPtr[7*8];

        e0=c0+c3;
        e1=c1+c2;
        e2=c1-c2;
        e3=c0-c3;

        d0=e0+e1;
        d4=e0-e1;
    
        value=((e2+e3)*_SQRT2_2+_V_MP)>>_CONSTFACTOR;
        d2=e3+value;
        d6=e3-value;

        a=c4+c5;
        b=c5+c6;
        c=c6+c7;
        d=c7;

        value1=b*_SQRT2_2;

        value2=(a-c)*_C_6_16;
        value=c*_C_2A6_16+value2;
    
        d1=d+((value1+value+_V_MP)>>_CONSTFACTOR);
        d7=d+((value1-value+_V_MP)>>_CONSTFACTOR);

        value=a*_C_2S6_16+value2;    

        d5=d-((value1-value+_V_MP)>>_CONSTFACTOR);
        d3=d-((value1+value+_V_MP)>>_CONSTFACTOR);

        pDst[0*8]=(Ipp16s)((d0*pQuantTable[0]+16384)>>15);
        pDst[1*8]=(Ipp16s)((d1*pQuantTable[1]+16384)>>15);
        pDst[2*8]=(Ipp16s)((d2*pQuantTable[2]+16384)>>15);
        pDst[3*8]=(Ipp16s)((d3*pQuantTable[3]+16384)>>15);
        pDst[4*8]=(Ipp16s)((d4*pQuantTable[4]+16384)>>15);
        pDst[5*8]=(Ipp16s)((d5*pQuantTable[5]+16384)>>15);
        pDst[6*8]=(Ipp16s)((d6*pQuantTable[6]+16384)>>15);
        pDst[7*8]=(Ipp16s)((d7*pQuantTable[7]+16384)>>15);

        pTempPtr++;
        pDst++;
        pQuantTable+=8;
    }
    return IPP_STATUS_OK;
}

/******************************************************************************
// Name:             ippiDCTQuantLSFwd_JPEG_8u16s
// Description:      Performs Forward DCT and quantization for single block.
// Input Arguments: 
//             pSrc: Identifies source data in 8x8.
//      pQuantTable: Identifies quantization table which was generated by
//                   ippiDCTQuantFwdTableInit_JPEG_16u32s.
//
// Output Arguments:
//             pDst: Identifies destination data in 8x8.
//                  
// Remarks:      
//                   1. The start address of "pSrc", "pDst" and "pQuantTable"
//                      shall be aligned at 4byte boundary.
//                   2. It is better to do this alignment at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   
// Returns:         
//    IPP_STATUS_OK: Succeeds.
//
******************************************************************************/
IPPFUN(IppStatus, ippiDCTQuantLSFwd_JPEG_8u16s) (const Ipp8u* pSrc, 
                                                 int   srcStep,
                                                 Ipp16s *pDst, 
                                                 const Ipp16u *pQuantTable)
{
    int i;
    int c0,c1,c2,c3,c4,c5,c6,c7;
    int d0,d1,d2,d3,d4,d5,d6,d7;
    int e0, e1, e2, e3, a,b,c,d;
    int value, value1, value2;
    Ipp16s *pTempPtr;

    _IPP_CHECK_ARG((NULL!=pSrc)&&(NULL!=pDst));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pDst));
    _IPP_CHECK_ARG(0!=srcStep);
    _IPP_CHECK_ARG(NULL!=pQuantTable);
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pQuantTable));

    pTempPtr=pDst;

    /* Do 1D-DCT in the each row */
    for (i=8; i>0; i--) {

        c0=pSrc[0]+pSrc[7]-256;
        c1=pSrc[1]+pSrc[6]-256;
        c2=pSrc[2]+pSrc[5]-256;
        c3=pSrc[3]+pSrc[4]-256;
        c4=pSrc[3]-pSrc[4];
        c5=pSrc[2]-pSrc[5];
        c6=pSrc[1]-pSrc[6];
        c7=pSrc[0]-pSrc[7];

        e0=c0+c3;
        e1=c1+c2;
        e2=c1-c2;
        e3=c0-c3;

        pTempPtr[0]=(Ipp16s)(e0+e1);
        pTempPtr[4]=(Ipp16s)(e0-e1);
    
        value=((e2+e3)*_SQRT2_2+_H_MP)>>_CONSTFACTOR;
        pTempPtr[2]=(Ipp16s)(e3+value);
        pTempPtr[6]=(Ipp16s)(e3-value);

        a=c4+c5;
        b=c5+c6;
        c=c6+c7;
        d=c7;

        value1=b*_SQRT2_2;

        value2=(a-c)*_C_6_16;
        value=c*_C_2A6_16+value2;
    
        pTempPtr[1]=(Ipp16s)(d+((value1+value+_H_MP)>>_CONSTFACTOR));
        pTempPtr[7]=(Ipp16s)(d+((value1-value+_H_MP)>>_CONSTFACTOR));

        value=a*_C_2S6_16+value2;    

        pTempPtr[5]=(Ipp16s)(d-((value1-value+_H_MP)>>_CONSTFACTOR));
        pTempPtr[3]=(Ipp16s)(d-((value1+value+_H_MP)>>_CONSTFACTOR));

        pSrc+=srcStep;
        pTempPtr+=8;
    }

    pTempPtr=pDst;

    /* Do 1D-DCT in the each col */
    for (i=8; i>0; i--) {

        c0=pTempPtr[0*8]+pTempPtr[7*8];
        c1=pTempPtr[1*8]+pTempPtr[6*8];
        c2=pTempPtr[2*8]+pTempPtr[5*8];
        c3=pTempPtr[3*8]+pTempPtr[4*8];
        c4=pTempPtr[3*8]-pTempPtr[4*8];
        c5=pTempPtr[2*8]-pTempPtr[5*8];
        c6=pTempPtr[1*8]-pTempPtr[6*8];
        c7=pTempPtr[0*8]-pTempPtr[7*8];

        e0=c0+c3;
        e1=c1+c2;
        e2=c1-c2;
        e3=c0-c3;

        d0=e0+e1;
        d4=e0-e1;
    
        value=((e2+e3)*_SQRT2_2+_V_MP)>>_CONSTFACTOR;
        d2=e3+value;
        d6=e3-value;

        a=c4+c5;
        b=c5+c6;
        c=c6+c7;
        d=c7;

        value1=b*_SQRT2_2;

        value2=(a-c)*_C_6_16;
        value=c*_C_2A6_16+value2;
    
        d1=d+((value1+value+_V_MP)>>_CONSTFACTOR);
        d7=d+((value1-value+_V_MP)>>_CONSTFACTOR);

        value=a*_C_2S6_16+value2;    

        d5=d-((value1-value+_V_MP)>>_CONSTFACTOR);
        d3=d-((value1+value+_V_MP)>>_CONSTFACTOR);

        pDst[0*8]=(Ipp16s)((d0*pQuantTable[0]+16384)>>15);
        pDst[1*8]=(Ipp16s)((d1*pQuantTable[1]+16384)>>15);
        pDst[2*8]=(Ipp16s)((d2*pQuantTable[2]+16384)>>15);
        pDst[3*8]=(Ipp16s)((d3*pQuantTable[3]+16384)>>15);
        pDst[4*8]=(Ipp16s)((d4*pQuantTable[4]+16384)>>15);
        pDst[5*8]=(Ipp16s)((d5*pQuantTable[5]+16384)>>15);
        pDst[6*8]=(Ipp16s)((d6*pQuantTable[6]+16384)>>15);
        pDst[7*8]=(Ipp16s)((d7*pQuantTable[7]+16384)>>15);

        pTempPtr++;
        pDst++;
        pQuantTable+=8;
    }
    return IPP_STATUS_OK;
}

/* EOF */
